#include <allegro.h>
#include <stdio.h>

#define GFX_W 1000
#define GFX_H 480
#define NB_IMAGES 4
#define BULLETSPEED 10

struct somajam {
	BITMAP * img_right[NB_IMAGES];
	BITMAP * img_left[NB_IMAGES];
	int x, y;
	int direction; // 0:right 1:left 2:up
};
typedef struct somajam somajam;
typedef struct{
	int x;
	int y;
	int w;
	int h;
}Sprite;
struct bullets
{
int a,b;
int alive;
int xspd,yspd;
}; 
typedef struct bullets bullets;






//utils
int get_pixel(BITMAP* Buffer,int x,int y);


//Module Background
BITMAP* load_background_bmp(char chemin_background[]);
void draw_background(BITMAP *Background,BITMAP*Buffer);
void destroy_background(BITMAP * Background);

//Module somajam
void load_somajam(somajam *somajam);
void destroy_somajam(somajam *somajam);
void init_somajam(somajam *somajam);

void move_somajam_right(somajam *somajam,int *compteur,BITMAP * Background);
void move_somajam_left(somajam *somajam,int *compteur,BITMAP * Background);
void jump_somajam(somajam *somajam,BITMAP * Background); //move up
void gravity(int *y);
int bounding_box_collision(Sprite sprite1,Sprite Sprite2);
int collision_background(Sprite sprite1,unsigned char Matrice_collision[GFX_W][GFX_H]);


void move_somajam(somajam *somajam,int *compteur,BITMAP * Background);
void draw_somajam(somajam somajam,BITMAP *Buffer, int compteur);
void temp(somajam *somajam);
void fireweapon(somajam somajam ,bullets *bullets);
void updatebullet(bullets *bullets);

int main() {

	char chemin_background[]="../images/background.bmp";
        char chemin_background_collision_bmp[]="../images/background_collision.bmp";


	BITMAP *Buffer;
	BITMAP *Background=NULL;
	BITMAP *BackgroundCol=NULL;
	somajam somajam;
        bullets bullets;

	int compteur;

	/* General initialization function */
        //install_timer();
       // srand(time(NULL));
	allegro_init();
	if (install_keyboard() == -1) {
		allegro_message("Error! %s", allegro_error);
		return (-1);
	}
	set_color_depth(24);
	if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, GFX_W, GFX_H, 0, 0) != 0) {
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); /* here’s the command for text mode */
		allegro_message("Unable to initialize video mode!\n%s\n", allegro_error);
		return (1);
	}

	Buffer = create_bitmap(SCREEN_W, SCREEN_H);
	//loading images
	//loading somajam
	load_somajam(&somajam);
	//loading background + background collision
	Background=load_background_bmp(chemin_background);
	BackgroundCol=load_background_bmp(chemin_background_collision_bmp);
	//loading background collision Map


	//init position & direction
	compteur = 0;
	init_somajam(&somajam);

	while (!key[KEY_ESC]) {
		//vider le buffer
		clear_bitmap(Buffer);
                
		//moving somajam
updatebullet(&bullets);
                if (key[KEY_SPACE])
        fireweapon(somajam,&bullets);
		move_somajam(&somajam,&compteur,BackgroundCol);
                
		//drawing background
		blit(Background, Buffer, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
		//drawing somajam
		draw_somajam(somajam,Buffer,compteur);
		//blit Buffer to screen
		blit(Buffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
              
              

		if (compteur == 10000)
			compteur = 0;
	}
	//destroy somajam
	destroy_somajam(&somajam);
	destroy_background(Background);
        destroy_bitmap(BackgroundCol);
	destroy_bitmap(Buffer);
        
	return (0);
}
END_OF_MAIN();

/*
 * module background
 */
int load_background_collision(unsigned char Mat_background[GFX_W][GFX_H],char chemin_backgnd_col[])

{
	int i,j,int_tmp;
	FILE *F;

	F=fopen(chemin_backgnd_col,"r");

	if(F==NULL){
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0); /* here’s the command for text mode */
		printf("\nErreur ouverture d fichier");
		return (-1);
	}

	for(j=0;j<GFX_H;j++){
		// lecture sur l'axe Y
		for(i=0;i<GFX_W;i++){
			// lecture sur l'axe X (=lecture d'une ligne)
			fscanf(F,"%d", &int_tmp);
			Mat_background[i][j]=(unsigned char)int_tmp;
		}
	}
	fclose(F);

	return (0);
}
void display_mat(unsigned char Mat_background[GFX_W][GFX_H])
{
	int i,j;
	for(i=0;i<GFX_W;i++){

			// lecture sur l'axe Y
			for(j=0;j<GFX_H;j++){
				// lecture sur l'axe X (=lecture d'une ligne)
				printf("%d ",Mat_background[i][j]);
			}
			printf("\n");
	}
}

BITMAP* load_background_bmp(char chemin_background[])
{
	BITMAP* Background;

	Background=load_bitmap(chemin_background, NULL);
	if(Background == NULL){
		set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
		allegro_message("Unable to load image !\n%s\n", allegro_error);
		return (NULL);
	}
	return (Background);

}


void draw_background(BITMAP *Background,BITMAP*Buffer)
{
	blit(Background, Buffer, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
}

void destroy_background(BITMAP * Background)
{
	destroy_bitmap(Background);
}

/*
 * module somajam
 */

void load_somajam(somajam *somajam)
{
	int i;
	char buf[50];
	for (i = 0; i < NB_IMAGES; i++) {
		sprintf(buf, "../images/right%d.bmp", i);
		somajam->img_right[i] = load_bitmap(buf, NULL);
		sprintf(buf, "../images/left%d.bmp", i);
		somajam->img_left[i] = load_bitmap(buf, NULL);
	}
}

void destroy_somajam(somajam *somajam)
{
	int i;
	for (i = 0; i < NB_IMAGES; i++) {
		destroy_bitmap(somajam->img_right[i]);
		destroy_bitmap(somajam->img_left[i]);
	}

}
void init_somajam(somajam *somajam)
{
	somajam->direction = 0;
	somajam->x = SCREEN_W / 2;
	somajam->y = SCREEN_H / 2;
}
void move_somajam_right(somajam *somajam,int *compteur,BITMAP * Background)
{
	Sprite sprite1;
	sprite1.x=somajam->x;
	sprite1.y=somajam->y;
	sprite1.w=somajam->img_right[*compteur % (NB_IMAGES-1)]->w;
	sprite1.h=somajam->img_right[*compteur % (NB_IMAGES-1)]->h;

	if (key[KEY_RIGHT] && (somajam->x < SCREEN_W - somajam->img_right[0]->w) && !collision_background_right(sprite1,Background)) {
		*compteur+=1;

		(somajam->x)+=1;
		somajam->direction = 0; //right
	}

}

void move_somajam_left(somajam *somajam,int *compteur,BITMAP * Background)
{
	Sprite sprite1;
	sprite1.x=somajam->x;
	sprite1.y=somajam->y;
	sprite1.w=somajam->img_left[*compteur % (NB_IMAGES-1)]->w;
	sprite1.h=somajam->img_left[*compteur % (NB_IMAGES-1)]->h;

	if (key[KEY_LEFT] && (somajam->x > 0 + somajam->img_left[0]->w) && !collision_background_left(sprite1,Background))
         {
		*compteur+=1;

		(somajam->x)-=1;
		somajam->direction = 1; //left
	}
}
void jump_somajam(somajam *somajam,BITMAP * Background)
{
	Sprite sprite1;
	sprite1.x=somajam->x;
	sprite1.y=somajam->y;
	sprite1.w=somajam->img_right[NB_IMAGES-1]->w;
	sprite1.h=somajam->img_right[NB_IMAGES-1]->h;

	if (key[KEY_UP] && (somajam->y > 0) && !collision_background_up(sprite1,Background) ) {
		(somajam->y)-=10;
		somajam->direction = 2; //jump
	}

}
void gravity_somajam(somajam *somajam,BITMAP * Background)
{
	Sprite sprite1;
	sprite1.x=somajam->x;
	sprite1.y=somajam->y;
	sprite1.w=somajam->img_right[0]->w;
	sprite1.h=somajam->img_right[0]->h;

	if(!collision_background_down(sprite1,Background))
		gravity(&(somajam->y));
}

void move_somajam(somajam *somajam,int *compteur,BITMAP * Background)
{
	move_somajam_right(somajam,compteur,Background);
	move_somajam_left(somajam,compteur,Background);
	jump_somajam(somajam,Background);
	gravity_somajam(somajam,Background);
	temp(somajam);
}
void draw_somajam(somajam somajam,BITMAP *Buffer, int compteur)
{
	static int last_direction;

	if (somajam.direction == 0){ //moving right

		draw_sprite(Buffer, somajam.img_right[compteur % (NB_IMAGES-1) ],somajam.x, somajam.y);
		last_direction=0;
	}

	if(somajam.direction == 1){ //moving left

		draw_sprite(Buffer, somajam.img_left[compteur % (NB_IMAGES-1) ],somajam.x, somajam.y);
		last_direction=1;
	}
	if (somajam.direction == 2 && last_direction==0) {	//jumping right

		draw_sprite(Buffer, somajam.img_right[NB_IMAGES - 1],somajam.x, somajam.y);
	}
	if (somajam.direction == 2 && last_direction==1) {	//jumping right

		draw_sprite(Buffer, somajam.img_left[NB_IMAGES - 1],somajam.x, somajam.y);
	}
}
void temp(somajam *somajam)
{
	if((somajam->y + somajam->img_right[0]->h) > SCREEN_H)
		somajam->y = SCREEN_H - somajam->img_right[0]->h;

}
/*
 * module collision
 */
void gravity(int *y)
{
	*y+=2;
}



int collision_background_right(Sprite sprite1,BITMAP* BackgroundCol)
{
	int x;
	int y;
	x=sprite1.x + sprite1.w;
	y=sprite1.y + (sprite1.h / 2);

	if( get_pixel(BackgroundCol,x,y)== 255)
		return (1);//collision with the middle right side of the sprite

	return (0);//no collision
}

int collision_background_left(Sprite sprite1,BITMAP* BackgroundCol)
{
	int x;
	int y;
	x=sprite1.x;
	y=sprite1.y + (sprite1.h /2);

	if( get_pixel(BackgroundCol,x,y)== 255)
		return (1); //collision with the middle left side of the sprite

	return (0); //no collision
}

int collision_background_down(Sprite sprite1,BITMAP* BackgroundCol)
{
	int x;
	int y;
	x=sprite1.x + (sprite1.w /2);
	y=sprite1.y + sprite1.h;

	if( get_pixel(BackgroundCol,x,y)== 255)
		return (1); //collision with the middle down side of the sprite

	return (0); //no collision

}

int collision_background_up(Sprite sprite1,BITMAP* BackgroundCol)
{
	int x;
	int y;
	x=sprite1.x + (sprite1.w /2);
	y=sprite1.y;

	if( get_pixel(BackgroundCol,x,y)== 255)
		return (1); //collision with the middle left side of the sprite

	return (0); //no collision

}

int bounding_box_collision(Sprite sprite1,Sprite sprite2)
{
	if ((sprite1.x > sprite2.x + sprite2.w - 1) || // is Sprite1 on the right side of Sprite2?
			(sprite1.y > sprite2.y + sprite2.h - 1) || // is b1 under b2?
			(sprite2.x > sprite1.x + sprite1.w - 1) || // is b2 on the right side of b1?
			(sprite2.y > sprite1.y + sprite1.h - 1)) // is b2 under b1?
	{
		// no collision
		return (0);
	}

	// collision
	return (1);
}
void updatebullet(bullets *bullets)
{
int x1 = bullets->a;
int y2 = bullets->b;
if (bullets->alive)
{
//erase bullet
rect(screen, x1-1, y2-1, x1+1, y2+1, 0);
//move bullet
bullets->a += bullets->xspd;
bullets->b += bullets->yspd;
x1 = bullets->a;
y2 = bullets->b;
//stay within the screen
if (x1 < 20 || x1 > SCREEN_W|| y2 < 20 || y2 > SCREEN_H)
{
bullets->alive = 0;
return;
}
//draw bullet
x1 = bullets->a;
y2 = bullets->b;
rect(screen, x1-1, y2-1, x1+1, y2+1, 30);
//look for a hit
if (getpixel(screen, bullets->a, bullets->b))
{
bullets->alive = 0;

}
//print the bullet’s position
textprintf_ex(screen, font, SCREEN_W/2-50, 1, 2, 0,"B1 %-3dx%-3d ",bullets->a, bullets->b);

}
}
/////////////////////////////////////////////////////////////////////////
// fireweapon function
// configure a bullet’s direction and speed and activate it
/////////////////////////////////////////////////////////////////////////
void fireweapon(somajam somajam,bullets *bullets)
{
int x1 = somajam.x;
int y2 = somajam.y;
//ready to fire again?
if (!bullets->alive)
{
bullets->alive = 1;
//fire bullet 
switch (somajam.direction)
{
//north
case 0:
bullets->a = x1;
bullets->b = y2-22;
bullets->xspd = 0;
bullets->yspd = -BULLETSPEED;
break;
//east
case 1:
bullets->a = x1+22;
bullets->b = y2;
bullets->xspd = BULLETSPEED;
bullets->yspd = 0;
break;
//south
case 2:
bullets->a = x1;
bullets->b = y2+22;
bullets->xspd = 0;
bullets->yspd = BULLETSPEED;
break;

}
}
}





int get_pixel(BITMAP* Buffer,int x,int y)
{
	int tmp;
	tmp=getpixel(Buffer,x,y);
	return((getr(tmp) + getb(tmp) + getg(tmp)) / 3);
}
